﻿using AiQiuQuan.Sport.Core.Tool;
using Microsoft.AspNetCore.Authentication;
using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using System.Security.Claims;
using System.Text;
using System.Text.Encodings.Web;
using System.Web;

namespace AiQiuQuan.Sport.Core.AspNetCore
{
    /// <summary>
    /// SimpleAuthHandler
    /// </summary>
    public class SimpleAuthHandler : AuthenticationHandler<AuthenticationSchemeOptions>
    {
        private readonly IMemoryCache _cache;

        /// <summary>
        /// 加密key
        /// </summary>
        public const string AES_KEY = "aiqiuquan.sp.key";

        /// <summary>
        /// 缓存过期分钟
        /// </summary>
        public const int ExpireMinute = 20;

        /// <summary>
        /// ctor
        /// </summary>
        public SimpleAuthHandler(
            IOptionsMonitor<AuthenticationSchemeOptions> options,
            IMemoryCache cache,
            ILoggerFactory loggerFactory,
            UrlEncoder encoder,
            ISystemClock clock)
            : base(options, loggerFactory, encoder, clock)
        {
            _cache = cache;
        }

        /// <summary>
        /// HandleAuthenticateAsync
        /// </summary>
        protected override async Task<AuthenticateResult> HandleAuthenticateAsync()
        {
            var key = "t";
            var key1 = "Authorization";
            var encryptInfo = Request.Headers[key1];
            if (string.IsNullOrWhiteSpace(encryptInfo))
            {
                encryptInfo = Request.Headers[key];
            }

            if (string.IsNullOrWhiteSpace(encryptInfo))
            {
                encryptInfo = Request.Query[key];
            }

            if (string.IsNullOrWhiteSpace(encryptInfo))
            {
                return AuthenticateResult.Fail($"Missing Authorization Header_{Request.Headers[key]}_{Request.Query[key]}_{Request.Headers[key1]}");
            }

            encryptInfo = HttpUtility.UrlDecode(encryptInfo, Encoding.UTF8);

            try
            {
                //解密信息
                var decryptInfo = AESCryptography.Decrypt(encryptInfo, AES_KEY);
                if (string.IsNullOrWhiteSpace(decryptInfo))
                {
                    return AuthenticateResult.Fail("decrypt faild");
                }

                //UserInfoAddDto
                //数据格式：id|name|p
                var claimArray = decryptInfo.Split('|');

                //缓存操作
                var cacheKey = $"{claimArray[0]}";
                if (string.IsNullOrWhiteSpace(_cache.Get<string>(cacheKey)))
                {
                    return AuthenticateResult.Fail("token expired");
                }

                _cache.Set<string>(cacheKey, encryptInfo, new TimeSpan(0, ExpireMinute, 0));

                //生成票据
                var ticket = BuildTicket(claimArray);
                await Task.CompletedTask;

                return AuthenticateResult.Success(ticket);
            }
            catch (Exception e)
            {
                return AuthenticateResult.Fail($"user data error_{e.Message}");
            }
        }

        #region private methods

        private AuthenticationTicket BuildTicket(string[] claimArray)
        {
            var claims = new[]
                {
                    new Claim("id", claimArray[0]),
                    new Claim("name", claimArray[1]),
                    new Claim("p",claimArray[2]),
                };
            var identity = new ClaimsIdentity(claims, Scheme.Name);
            var principal = new ClaimsPrincipal(identity);
            var ticket = new AuthenticationTicket(principal, Scheme.Name);

            return ticket;
        }

        #endregion private methods
    }
}